#ifndef OUTPUT_PROXY_H
#define OUTPUT_PROXY_H
#pragma once

#include <KDebugServer.h>
#include <iostream>
#include <sstream>

class OutputProxy : public KDebugServer {
public:
    enum Style {
        Dark        = FOREGROUND_INTENSITY,
        Gray        = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
        White       = Gray | Dark,
        DarkRed     = FOREGROUND_RED,
        DarkGreen   = FOREGROUND_GREEN,
        DarkBlue    = FOREGROUND_BLUE,
        DarkCyan    = DarkGreen | DarkBlue,
        DarkMagenta = DarkRed | DarkBlue,
        DarkYellow  = DarkRed | DarkGreen,
        Red         = DarkRed | Dark,
        Green       = DarkGreen | Dark,
        Blue        = DarkBlue | Dark,
        Cyan        = DarkCyan | Dark,
        Magenta     = DarkMagenta | Dark,
        Yellow      = DarkYellow | Dark,
        // Special
        Flush       = 0,
        Header      = BACKGROUND_INTENSITY | Blue,
        Note        = BACKGROUND_INTENSITY
    };
public:
    explicit OutputProxy(KPageList *pool = NULL, u_short port = 0)
        : KDebugServer(pool, port) {}
public:
    inline OutputProxy &operator<<(Style style);
    template <class T>
    inline OutputProxy &operator<<(const T &rhs);
public:
    inline void setTitle(const std::string &title);
};

OutputProxy &OutputProxy::operator<<(Style style)
{
    if (style == OutputProxy::Flush) {
        std::cout << std::flush;
    } else {
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), WORD(style));
        setAttr(0, uint32_t(style));
    }
    return *this;
}

template <class T>
OutputProxy &OutputProxy::operator<<(const T &rhs)
{
    std::ostringstream oss;
    oss << rhs;
    if (!oss.str().empty()) {
        std::cout << oss.str();
        setInfo(oss.str());
    }
    return *this;
}

void OutputProxy::setTitle(const std::string &title)
{
    SetConsoleTitleA(title.c_str());
    setInfo(title, true);
}

#endif // OUTPUT_PROXY_H